package com.yunkeji.api.index.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunkeji.api.common.service.SysParamService;
import com.yunkeji.api.index.bo.RankingListBo;
import com.yunkeji.api.index.bo.SendHelloList;
import com.yunkeji.api.index.bo.UserListBo;
import com.yunkeji.api.index.mapper.ApiSysHelloMapper;
import com.yunkeji.api.index.service.IndexService;
import com.yunkeji.api.index.vo.*;
import com.yunkeji.api.user.mapper.ApiAppUserMapper;
import com.yunkeji.api.user.service.AppUserInfoService;
import com.yunkeji.common.constant.CacheConstants;
import com.yunkeji.common.constant.SysConfigConsts;
import com.yunkeji.common.core.domain.model.LoginUser;
import com.yunkeji.common.core.page.TableDataInfo;
import com.yunkeji.common.enums.app.EnableEnum;
import com.yunkeji.common.enums.app.SexEnum;
import com.yunkeji.common.exception.AppServiceException;
import com.yunkeji.common.helper.LoginHelper;
import com.yunkeji.common.msg.PushMessage;
import com.yunkeji.common.msg.bo.PrivateMsg;
import com.yunkeji.common.utils.redis.RedisUtils;
import com.yunkeji.dao.domain.*;
import com.yunkeji.dao.mapper.AppUserExtMapper;
import com.yunkeji.dao.mapper.AppUserWalletMapper;
import com.yunkeji.dao.mapper.SysHelloDetailMapper;
import com.yunkeji.dao.vo.SysHelloVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/** @author 老张 */
@RequiredArgsConstructor
@Service
@Slf4j
public class IndexServiceImpl implements IndexService {

    private final ApiAppUserMapper apiAppUserMapper;
    private final AppUserExtMapper appUserExtMapper;
    private final ApiSysHelloMapper apiSysHelloMapper;
    private final SysParamService sysParamService;
    private final AppUserInfoService appUserInfoService;
    private final AppUserWalletMapper appUserWalletMapper;
    private final SysHelloDetailMapper sysHelloDetailMapper;

    /**
     * 查询列表
     *
     * @author 老张
     */
    @Override
    public TableDataInfo<UserListVo> queryUserList(UserListBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        // bo.setSex(appUserInfoService.getOppositeSex(loginUser).getCode());
        bo.setUid(loginUser.getUserId());
        Page<UserListVo> vos = apiAppUserMapper.pageUserList(bo.build(), bo);
        return TableDataInfo.build(vos);
    }

    /**
     * 打招呼列表
     *
     * @author 老张
     */
    @Override
    public List<RandomMatchListVo> helloList() {
        SexEnum sex = appUserInfoService.getOppositeSex(LoginHelper.getLoginUser());
        return apiAppUserMapper.randomMatch(LoginHelper.getPlatformId(), sex.getCode(), 9);
    }

    /**
     * 发送打招呼
     *
     * @author 老张
     */
    @Override
    public void sendHelloList(SendHelloList sendHelloList) {
        List<Long> ids = sendHelloList.getIds();
        if (ids.size() > 1) {
            if (ids.size() > 9) {
                throw AppServiceException.paramException("最多只能打招呼9人");
            }
        }
        HelloContentVo helloContent = null;
        if (sendHelloList.getHelloId() != null) {
            SysHelloVo sysHelloVo = apiSysHelloMapper.selectVoById(sendHelloList.getHelloId());
            helloContent = BeanUtil.toBean(sysHelloVo, HelloContentVo.class);
        } else {
            AppUser appUser = apiAppUserMapper.selectById(LoginHelper.getUserId());
            helloContent = apiSysHelloMapper.randomOne(1, appUser.getSex()).get(0);
        }
        AppUser appUser = apiAppUserMapper.selectById(LoginHelper.getUserId());
        AppUserExt appUserExt = appUserExtMapper.selectById(appUser.getId());
        PushMessage.sendTextBatchPrivate(
                appUser.getPlatformId(),
                ids,
                PrivateMsg.builder()
                        .content(helloContent.getContent())
                        .nickname(appUserExt.getNickName())
                        .headUrl(appUserExt.getHeadUrl())
                        .id(appUser.getId())
                        .platformId(appUser.getPlatformId())
                        .build());

        List<SysHelloDetail> details = new ArrayList<>();
        for (Long id : ids) {
            details.add(
                    SysHelloDetail.builder().recUid(id).sendUid(appUser.getPlatformId()).build());
        }
        try {
            sysHelloDetailMapper.insertBatch(details);
        } catch (Exception e) {
            log.error("插入异常，{}", e.getMessage());
        }
    }

    /**
     * 快速匹配
     *
     * @author 老张
     */
    @Override
    public StartMatchVo startMatch() {
        // TODO 从匹配池中获取用户,目前只需要随机查询对立性别

        AppUserVip appUserVip =
                AppUserVip.builder().build().selectById(LoginHelper.getLoginUser().getUserId());
        // 非会员免费次数
        String configValue = sysParamService.selectConfigByKey(SysConfigConsts.非会员免费匹配次数);
        Boolean isVip =
                appUserVip.getCommonVipFlag().equals(EnableEnum.YES.getCode())
                        && appUserVip.getCommonVipExpireTime().getTime() >= new Date().getTime();
        String martchKey = CacheConstants.MATCH_LIMIT + appUserVip.getId();
        if (!isVip) {
            if (appUserVip.getCommonVipFlag().equals(EnableEnum.NO.getCode())) {
                Object cacheObject = RedisUtils.getCacheObject(martchKey);
                if (cacheObject != null) {
                    Integer times = (Integer) cacheObject;
                    if (times >= Integer.parseInt(configValue)) {
                        throw AppServiceException.paramException(
                                "您暂未开通会员,每日视频速配免费匹配" + configValue + "次,开通会员将不限制视频匹配次数~");
                    }
                }
            }
        }
        SexEnum sex = appUserInfoService.getOppositeSex(LoginHelper.getLoginUser());

        AppUser appUser = apiAppUserMapper.selectById(LoginHelper.getUserId());
        BigDecimal price = BigDecimal.ZERO;
        if (appUser.getSex().equals(SexEnum.男.getCode())) {
            // 男匹配女,需要女号的价格小于等于男号的余额
            AppUserWallet appUserWallet = appUserWalletMapper.selectById(appUser.getId());
            price = appUserWallet.getGoldBalance();
        } else {
            // 女匹配男需要男方的钱包余额大于等于女号设置的最低金额
            price = appUser.getVideoPrice();
        }
        StartMatchVo startMatchVo =
                apiAppUserMapper.startMatch(sex.getCode(), LoginHelper.getUserId(), price);
        if (startMatchVo != null) {
            // fansonคิดถึง 随机匹配30分钟内不重复匹配，这个好像没做哇？
            // 我明天加一下。
            String key =
                    CacheConstants.START_MATCH_LIMIT
                            + LoginHelper.getUserId()
                            + ":"
                            + startMatchVo.getId();
            Object cacheObject = RedisUtils.getCacheObject(key);
            if (cacheObject != null) {
                return null;
            } else {
                RedisUtils.setCacheObject(key, "1", Duration.ofMinutes(30));
            }
            // 每日十次且匹配成功才算
            long between =
                    DateUtil.between(new Date(), DateUtil.endOfDay(new Date()), DateUnit.SECOND);
            Boolean matchFlag =
                    RedisUtils.setAtomicValueAdd(
                            martchKey,
                            Integer.parseInt(configValue),
                            Integer.parseInt(String.valueOf(between)));
        }
        return startMatchVo;
    }

    /**
     * 灵魂匹配
     *
     * @author 老张
     */
    @Override
    public List<RandomMatchListVo> soulMatch() {
        SexEnum sex = appUserInfoService.getOppositeSex(LoginHelper.getLoginUser());
        Comparator<RandomMatchListVo> comparing =
                Comparator.comparing(
                        RandomMatchListVo::getRecentlyAccessTime,
                        Comparator.nullsLast(Comparator.naturalOrder()));
        return apiAppUserMapper.randomMatch(LoginHelper.getPlatformId(), sex.getCode(), 9).stream()
                .sorted(comparing)
                .collect(Collectors.toList());
    }

    @Override
    public List<HelloContentVo> helloContent() {
        AppUser appUser = apiAppUserMapper.selectById(LoginHelper.getUserId());
        return apiSysHelloMapper.randomOne(9, appUser.getSex());
    }

    @Override
    public TableDataInfo<RankingListVo> getWealthyRanking(RankingListBo bo) {
        return TableDataInfo.build(apiAppUserMapper.getWealthyRanking(bo.build(), bo));
    }

    @Override
    public TableDataInfo<RankingListVo> getInviteRanking(RankingListBo bo) {
        return TableDataInfo.build(apiAppUserMapper.getInviteRanking(bo.build(), bo));
    }
}
